﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;

using HAUtil;

namespace HA.ModFlow.Domain.DomainLayer
{

    /// <summary>
    /// 用于表示水概念模型中的网格相关数据
    /// </summary>
    [Serializable]
   public class WaterGrid
   {

       #region 构造函数

        public WaterGrid(GridData parent)

        {

            this._parentGridData = parent;
            

            _layers = new List<GridLayer>();




            for (int i = 0; i < this._parentGridData.LayersCount; i++)
            {
                GridLayer gl = new GridLayer(this._parentGridData.RowsCount, this._parentGridData.ColsCount);
                gl.ParentGrid = this;

                _layers.Add(gl);

            }

 

        }

       //public WaterGrid(int nrows,int ncols,int nlayers)
       // {
          
       //     //_topElevation=new double[nrows,ncols];
 
       // }

       #endregion

       #region 事件部分

       // [field:NonSerialized]
       //public event DefaultHandler BoundChanged;
       //    [field: NonSerialized]
       // public event DefaultHandler InitHeadChanged;

       // public event DefaultHandler ConfiningBedChanged;

       // public event DefaultHandler HaveConfiningBedChanged;


        [field:NonSerialized]
        public event EventHandler<WaterGridModifiedEventArgs> WaterGridModified;

       #endregion


        #region 属性数据

        public GridLayer this[int index]
        {
            get { return this._layers[index]; }

        }


       List<GridLayer> _layers;

       public List<GridLayer> Layers
       {
           get { return _layers; }
         
       }


       GridData _parentGridData;

       public GridData ParentGridData
       {
           get { return _parentGridData; }
          
       }


        #endregion


       //double[,] _topElevation;

        //public double[,] TopElevation
        //{
        //    get { return _topElevation; }
        //    set { _topElevation = value; }
        //}

        /// <summary>
        /// 获得所有的ibound边界条件值
        /// 返回是引用传递,使用时必须用此属性副本
        /// </summary>
        /// <returns></returns>
        public List<int[,]> GetIBounds()
        {

            List<int[,]> bounds = new List<int[,]>();
            foreach (GridLayer  layer in this._layers)
            {
                bounds.Add(layer.IBound);
            }

            return bounds;

        }
        /// <summary>
        /// 获得指定层的ibound边界条件值  
        /// </summary>
        /// <param name="layerIndex"></param>
        /// <returns></returns>
  
        public int[,] GetLayerIBounds(int layerIndex)
        { 
            //小李加

            if (this._layers ==null )
            {
                return null;
            }
            if (0 <= layerIndex && layerIndex < _layers.Count )
            {

                int[,] layerBounds = (int[,])this._layers[layerIndex].IBound.Clone();

                return layerBounds;

            }
            else
            {
                return null;
            }

        }

        /// <summary>
        /// 设置所有的ibound 边界条件
        /// </summary>
        /// <param name="bounds"></param>
        public void SetIBounds( List<int[,]> bounds)
        {
            int i=0;

            bool layChanged = false;//记录各层是否发生变化

            bool changed = false;//记录整个IBound是否发生变化

            bool isEffecitiveChanged=false;//记录是否有某个单元格的有效性在 有效 和 无效 之间发生了变化

            foreach (GridLayer layer in this._layers)
            {
                //需要检查两个问题：1，对于每一层layer，数据是否变化；2，对于整个网格，是否有某个cell从有效变为无效或者相反

                for (int j = 0; j < bounds[i].GetLength(0); j++)
                //for (int j = 0; j < bounds[i].GetLength(0) & layChanged == false; j++)
                {
                    for (int k = 0; k < bounds[i].GetLength(1); k++)
                    {
                        if (layer.IBound[j, k] != bounds[i][j, k])
                        {
                            layChanged = true;

                            if (changed == false)
                            {
                                changed = true;
                            }

                            if (layer.IBound[j, k] == 0 || bounds[i][j, k] == 0)
                            {
                                //在有效和无效之间发生了变化  即  0  和  1，-1之间

                                isEffecitiveChanged = true;

                            }


                            if (layChanged == true && isEffecitiveChanged == true)
                            {
                                //如果该层数据改变并且存在有效无效之间的转换，则

                                break;
                            }



                            //break;
                        }

                    }

                    if (layChanged == true && isEffecitiveChanged == true)
                    {
                        break;
                    }


                }

                if (layChanged == true)
                {
                    layer.IBound = bounds[i];
                }

                i++;
                layChanged = false;
            }
            if (changed == true)
            {
                //说明：当修改IBound值后，如果变化前后存在某个体单元格的有效性标志在有效和无效之间发生了改变
                //则需要根据IBound值对网格边框个点进行高程插值，重新计算高程，无效体单元格对应的面单元的高程值将不会影响插值
                //  此处需要另外添加一个事件通知


                if (isEffecitiveChanged)
                {
                    //存在单元格在有效和无效之间发生 了变化

                    if (this._parentGridData !=null )
                    {
                        this._parentGridData.AskElevationChanged();//更新高程
                    }

                }

            

                if (WaterGridModified!=null)
                {
                    WaterGridModified(this,new WaterGridModifiedEventArgs (bounds,WaterGridModifiedType.IBOUND));
                    
                }
               
            }
 
        }



      

        /// <summary>
        /// 跟新局部ibound的值
        /// </summary>
        /// <param name="indices"></param>
        /// <param name="Value"></param>
        public void SetPartIBounds(List<int> indices, int Value)
        {

            bool changed = false;//记录整个IBound是否发生变化
           

            bool isEffecitiveChanged = false;//记录是否有某个单元格的有效性在 有效 和 无效 之间发生了变化


            foreach (int item in indices)
            {

                int[] ijk = this.ParentGridData.GetIJK(item);//index转成 i j k

                int i = ijk[0];

                int j = ijk[1];

                int k = ijk[2];

                if (this.Layers[k-1].IBound[i-1,j-1]!=Value)
                {
                    //需要变化

                    this.Layers[k - 1].IBound[i - 1, j - 1] = Value;

                    changed = true;


                    if (this.Layers[k-1].IBound[i-1,j-1]==0||Value ==0)
                    {
                        //是否是有效和无效的转变
                        isEffecitiveChanged = true;
                    }

                }
          





            }


            if (changed)
            {


                //说明：当修改IBound值后，如果变化前后存在某个体单元格的有效性标志在有效和无效之间发生了改变
                //则需要根据IBound值对网格边框个点进行高程插值，重新计算高程，无效体单元格对应的面单元的高程值将不会影响插值
                //  此处需要另外添加一个事件通知


                if (isEffecitiveChanged)
                {
                    //存在单元格在有效和无效之间发生 了变化

                    if (this._parentGridData != null)
                    {
                        this._parentGridData.AskElevationChanged();//更新高程
                    }

                }




                if (WaterGridModified != null)
                {
                    WaterGridModified(this, new WaterGridModifiedEventArgs(null, WaterGridModifiedType.IBOUND));

                }
                
            }



        }



        public int GetConstantCellCount()
        {
            int n = 0;

            foreach (GridLayer layer in this._layers)
            {

                n=n+ layer.GetConstantCellCount();
            }

            return n;
        }




       /// <summary>
        /// 获得所有的初始水头值
        /// </summary>
        /// <returns></returns>
        public List<double[,]> GetInitHead()
        {

            List<double[,]> initHead = new List<double[,]>();
            foreach (GridLayer layer in this._layers)
            {
                initHead.Add(layer.InitHead);
            }

            return initHead;

        }

        /// <summary>
        /// 获得指定层初始水头值
        /// </summary>
        /// <param name="layerIndex"></param>
        /// <returns></returns>
        public double[,] GetLayerInitHead(int layerIndex)
        {
            //小李加

            if (this._layers == null)
            {
                return null;
            }
            if (0 <= layerIndex && layerIndex < _layers.Count )
            {

                double[,] layerInitHead = (double[,])this._layers[layerIndex].InitHead.Clone();

                return layerInitHead;

            }
            else
            {
                return null;
            }

        }


        /// <summary>
        /// 设置所有的初始水头值
        /// </summary>
        /// <param name="heads"></param>
        public void SetInitHeads(List<double[,]> heads)
        {
            int i = 0;
            bool layChanged = false;
            bool changed = false;

            foreach (GridLayer layer in this._layers)
            {
                for (int j = 0; j < heads[i].GetLength(0) & layChanged == false; j++)
                {
                    for (int k = 0; k < heads[i].GetLength(1); k++)

                        if (layer.InitHead[j, k] != heads[i][j, k])
                        {
                            layChanged = true;
                            if (changed == false)
                            {
                                changed = true;
                            }
                            break;
                        }
                }

                if (layChanged == true)
                {
                    layer.InitHead = heads[i]; 
                }

                i++;
                layChanged = false;
            }
            if (changed == true)
            {
                if (WaterGridModified!=null)
                {
                    WaterGridModified(this,new WaterGridModifiedEventArgs(heads,WaterGridModifiedType.INITHEAD));
                    
                }


               
            }

        }

        /// <summary>
        /// 获得所有的隔水层值
        /// </summary>
        /// <returns></returns>
        public List<double[,]> GetConfiningBed()
        {

            List<double[,]> confiningBed = new List<double[,]>();
            foreach (GridLayer layer in this._layers)
            {
                confiningBed.Add(layer.ConfinedBedElevation);
            }

            return confiningBed;

        }

        /// <summary>
        /// 设置所有的隔水层值
        /// </summary>
        public void SetConfiningBeds(List<double[,]> beds)
        {
            int i = 0;
            bool layChanged = false;
            bool changed = false;

            foreach (GridLayer layer in this._layers)
            {
                for (int j = 0; j < beds[i].GetLength(0) & layChanged == false; j++)
                {
                    for (int k = 0; k < beds[i].GetLength(1); k++)

                        if (layer.ConfinedBedElevation[j, k] != beds[i][j, k])
                        {
                            layChanged = true;
                            if (changed == false)
                            {
                                changed = true;
                            }
                            break;
                        }
                }

                if (layChanged == true)
                {
                    layer.ConfinedBedElevation = beds[i];

                }

                i++;
                layChanged = false;
            }
            if (changed == true)
            {
                if (WaterGridModified!=null)
                {
                    WaterGridModified(this,new WaterGridModifiedEventArgs(beds,WaterGridModifiedType.CONFIEDELEVATION));
                    
                }
               
            }

        }

        /// <summary>
        /// 获取是否含有隔水层
        /// </summary>
        public List<bool> GetIsHaveConfiningBed()
        {
            List<bool> haveConfiningBed = new List<bool>();
            foreach (GridLayer layer in this._layers)
            {
                haveConfiningBed.Add(layer.IsHaveConfiningBed);
            }

            return haveConfiningBed;
            
        }
        /// <summary>
        /// 设置是否含有隔水层
        /// </summary>
        public void SetIsHaveConfiningBeds(List<bool> isHaves)
        {
            int i = 0;
            bool layChanged = false;
            bool changed = false;

            foreach (GridLayer layer in this._layers)
            {
                if (layer.IsHaveConfiningBed != isHaves[i])
                {
                    layChanged = true;
                    if (changed == false)
                    {
                        changed = true;
                    }
                    layer.IsHaveConfiningBed = isHaves[i];

                }  
                i++;
                layChanged = false;
            }
            if (changed == true)
            {
                if (WaterGridModified!=null)
                {
                    WaterGridModified(this,new WaterGridModifiedEventArgs(isHaves,WaterGridModifiedType.CONFIEDLAYER));
                    
                }

                //if (HaveConfiningBedChanged != null)
                //{
                //    HaveConfiningBedChanged();
                //}
            }
        }

        public List<bool> GetIsBottomLayer()
        {
            List<bool> isBottonLayer= new List<bool>();
            foreach (GridLayer layer in this._layers)
            {
               isBottonLayer.Add(layer.IsBottomLayer);
            }

            return isBottonLayer;
        }

        public List<int> GetLayerIndexList()
        {
            
            List<int> layerIndexList=new List<int>();
            foreach (GridLayer layer in this._layers)
            {
                //layerIndexList从1开始计数
                layerIndexList.Add(layer.LayerIndex+1);
               
            }

            return layerIndexList;
        }

        public void AddRow()
        {
 
        }

        public void AddColumn()
        {
 
        }

    }
}
